package com.yc;

import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.input.structured.StructuredPrompt;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.model.output.structured.Description;
import dev.langchain4j.service.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static java.time.Duration.ofSeconds;

public class _10_AiServiceAdvance {

    static  String apiKey=System.getenv("DEEPSEEK_API_KEY");
    static OpenAiChatModel model = OpenAiChatModel.builder()
            .apiKey(apiKey)
            .modelName("deepseek-chat")
            .baseUrl("https://api.deepseek.com")
            .logRequests(true)
            .logResponses(true)
            .build();

    //带系统提示词和用户提示词  提供翻译(语言可指定),给文章写总结
    static class Ai_servie_with_system_and_user_messages_example {
        interface TranslatorService{
            @SystemMessage("你是{{language}}的专业翻译")
            @UserMessage("翻译以下内容:{{text}}")
            String translate(@V("text") String text, @V("language") String language);

            @SystemMessage("总结用户的每条消息为{{n}}句话.")
            List<String>   summarize(@UserMessage String text,@V("n") int n);


        }

        public static void main(String[] args) {
            //通过动态代理机制生成Ai Srrvice的代理类对象
            TranslatorService translatorService=AiServices.create(TranslatorService.class,model);
            String answer=translatorService.translate("你好","法语");
            System.out.println(answer);

            String text="etMapping(\"/create\")：映射 HTTP GET 请求到/create路径\n" +
                    "@RequestParam：将请求参数绑定到方法参数\n" +
                    "userId：请求参数名为userId，对应 URL 中的useId=2（注意：URL 参数名是useId，但代码中是userId，可能存在拼写不一致）\n" +
                    "productId：请求参数名为productId，对应 URL 中的productId=100\n" +
                    "方法逻辑：调用OrderService的createOrder方法创建订单，并返回订单对象";
            List<String> answer2=translatorService.summarize(text,2);
            System.out.println(answer2);
        }

    }

    static class Sentiment_Extracting_Ai_Service_Example{
        enum Sentiment{
            POSITIVE,NEUTRAL,NEGATIVE
        }
        interface SentimentAnalyzerService{
            //情绪分析器
            @UserMessage(" 请分析{{it}}的情绪")
            Sentiment analyze(@V("it") String text);
            @UserMessage("以下的句子{{it}}是否为正向情绪?")
            boolean isPositive(@V("it") String text);
            @UserMessage("以下的句子{{it}}是否为负向情绪?")
            boolean isNegative(@V("it") String text);
        }

        public static void main(String[] args) {
            SentimentAnalyzerService sentimentAnalyzerService=AiServices.create(SentimentAnalyzerService.class,model);
            String text="i love you";
            boolean answer=sentimentAnalyzerService.isPositive(text);
            System.out.println(answer);

            Sentiment sentiment=sentimentAnalyzerService.analyze(text);
            System.out.println(sentiment);
        }
    }

    //酒店评论的AI分析服务
    static class Hotel_Review_Analysis_Service_Example{
        //1.设定评论类别的枚举
        public enum IssueCategory{
            MAINTENANCE_ISSUE,CLEANING_ISSUE,LOCATION_ISSUE,GENERAL_ISSUE,SERVICE_ISSUE,FACILITY_ISSUE,OVERALL_EXPERIENCE,CONNECTIVITY_ISSUE
        }
        interface HotelReviewIssueAnalyzerService{
            @UserMessage("请分析以下评论:{{review}}")
            IssueCategory analyze(@V("review") String review);
        }

        public static void main(String[] args) {
            HotelReviewIssueAnalyzerService hotelReviewIssueAnalyzerService=AiServices.create(HotelReviewIssueAnalyzerService.class,model);
            String review = "酒店整体风格比较气派，房间布局也很简洁。洗漱间也做到了干湿分离，洗漱台也很长，很方便女生梳妆";
            List<IssueCategory> answer= Collections.singletonList(hotelReviewIssueAnalyzerService.analyze(review));
            answer.forEach(System.out::println);
        }
    }
    /// 抽取数字服务
    static class Number_Extracting_Ai_Service_Example{
        interface NumberExtractorService{
            @UserMessage("请从{{it}}中提取数字")
            int extractInt(@V("it") String text);
            @UserMessage("请从{{it}}中提取数字")
            float extractFloat(@V("it") String text);
            @UserMessage("请从{{it}}中提取数字")
            double extractDouble(@V("it") String text);
            @UserMessage("请从{{it}}中提取数字")
            long extractLong(@V("it") String text);
            @UserMessage("请从{{it}}中提取数字")
            BigDecimal extractBigDecimal(@V("it") String text);
            @UserMessage("请从{{it}}中提取数字")
            BigInteger extractBigInteger(@V("it") String text);
        }

        public static void main(String[] args) {
            NumberExtractorService numberExtractorService=AiServices.create(NumberExtractorService.class,model);
            String text="我今年18岁,身高1.8米,体重70公斤,年薪30万,电话号13888";
            int answer=numberExtractorService.extractInt(text);
            System.out.println(answer);
            float answer2=numberExtractorService.extractFloat(text);
            System.out.println(answer2);
            BigDecimal answer3=numberExtractorService.extractBigDecimal(text);
            System.out.println(answer3);
        }
    }


    //抽取时间和日期
    static class Date_Extracting_Ai_Service_Example{
        interface DateExtractorService{
            @UserMessage("请从{{it}}中提取日期")
            LocalDate extractDate(@V("it") String text);
            @UserMessage("请从{{it}}中提取时间")
            LocalTime extractTime(@V("it") String text);
            @UserMessage("请从{{it}}中提取日期和时间")
            LocalDateTime extractDateTime(@V("it") String text);
    }
    public static void main(String[] args) {
            DateExtractorService dateExtractorService=AiServices.create(DateExtractorService.class,model);
            String text="会议安排在 2025 年 06 月 30 日（下周一）下午 3 点 15 分，需提前 15 分钟到场。另外，季度报告提交截止时间为 2025-07-10 23:59:59，逾期将无法上传。";
            LocalDate date = dateExtractorService.extractDate(text);
            System.out.println(date);
            LocalTime time = dateExtractorService.extractTime(text);
            System.out.println(time);
            LocalDateTime dateTime = dateExtractorService.extractDateTime(text);
            System.out.println(dateTime);
        }
    }

    //抽取POJO对象
    static class POJO_Extracting_Ai_Service_Example{
        static class Person{
            @Description("姓名")
            private String firstName;
            private String lastName;
            private LocalDate birthDate;
            private String gender;

            @Override
            public String toString() {
                return "Person{" +
                        "firstName='" + firstName + '\'' +
                        ", lastName='" + lastName + '\'' +
                        ", birthDate=" + birthDate +
                        ", gender='" + gender + '\'' +
                        '}';
            }
        }
        interface PersonExtractorService{
            @UserMessage("请从{{it}}中提取个人信息")
            Person extract( String text);
        }
        public static void main(String[] args) {
             String apiKey=System.getenv("DEEPSEEK_API_KEY");
            OpenAiChatModel model = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .modelName("deepseek-chat")
                    .baseUrl("https://api.deepseek.com")
                    .logRequests(true)
                    .logResponses(true)
                    .build();
            PersonExtractorService personExtractorService=AiServices.create(PersonExtractorService.class,model);
            String text="张三，男，1990-01-01出生";
            Person person = personExtractorService.extract(text);
            System.out.println(person);
        }
    }
    // 从一段话中,抽取信息形成一个订单(订单系统)
    static class OrderPOJO_Extracting_Ai_Service_Example{
        static class OrderItem{
            @Description("菜品名称")
            private String name;
            @Description("数量")
            private int count;

            @Override
            public String toString() {
                return "OrderItem{" +
                        "name='" + name + '\'' +
                        ", count=" + count +
                        '}';
            }
        }
        static class Orders{
            @Description("订单项集合")
            private List<OrderItem> items;
            @Description("送餐地址")
            private String address;
            @Description("联系电话")
            private String phone;
            @Description("附言")
            private String note;
            @Description("收餐人")
            private String receiver;

            @Override
            public String toString() {
                return "Orders{" +
                        "items=" + items +
                        ", address='" + address + '\'' +
                        ", phone='" + phone + '\'' +
                        ", note='" + note + '\'' +
                        ", receiver='" + receiver + '\'' +
                        '}';
            }
        }
        interface OrderExtractorService{
            @UserMessage("请从{{it}}中提取订单信息")
            Orders extract(String text);
        }
        public static void main(String[] args) {
            String apiKey=System.getenv("DEEPSEEK_API_KEY");
            OpenAiChatModel model = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .modelName("deepseek-chat")
                    .baseUrl("https://api.deepseek.com")
                    .logRequests(true)
//                    .logResponses(true)
                    .responseFormat("josn")
                    .strictJsonSchema(true)
                    .build();
            OrderExtractorService orderExtractorService=AiServices.create(OrderExtractorService.class,model);
            String text="请给湖南工学院润泽公寓邓懿送餐,一个辣椒炒肉,一个水煮鸡蛋,两瓶快乐,电话1232131,附言:不要等太久";
            Orders orders = orderExtractorService.extract(text);
            System.out.println(orders);
        }
    }

    //将prompt提示词与AI service相结合:用户提供菜名和原料,生成对应的菜的制作流程
    static class POJO_with_Prompt_Example{
        static class Recipe{
            @Description("显示的标题,最多五个字")
            private String title;
            @Description("对菜品的一段短的描述,最多两句话")
            private String description;
            @Description("制作流程,每一步骤最多一句话")
            private List<String> steps;
            @Description("制作时间,单位分钟")
            private int time;

            @Override
            public String toString() {
                return "Recipe{" +
                        "title='" + title + '\'' +
                        ", description='" + description + '\'' +
                        ", steps=" + steps +
                        ", time=" + time +
                        '}';
            }
        }
        static class Complex_Prompt_Template_Example {
            @StructuredPrompt({
                    "create a recipe for a {{dish}} dish with the following ingredients:{{ingredients}}",
                    "Structure your answer in the following way:",
                    "Recpie name...",
                    "Description...",
                    "Preparation time...",
                    "Required ingredients...",
                    "Instructions..."
            })
            static class CreateRecipePrompt {
                String dish;
                List<String> ingredients;

                CreateRecipePrompt(String dish, List<String> ingredients) {
                    this.dish = dish;
                    this.ingredients = ingredients;
                }
            }


        interface Chef{
            Recipe createRecipeFrom(String... ingredients);
            Recipe craeteRecipe(CreateRecipePrompt prompt);
            }
            public static void main(String[] args) {
                String apiKey=System.getenv("DEEPSEEK_API_KEY");
                OpenAiChatModel model = OpenAiChatModel.builder()
                        .apiKey(apiKey)
                        .modelName("deepseek-chat")
                        .baseUrl("https://api.deepseek.com")
                        .logRequests(true)
//                    .logResponses(true)
                        .responseFormat("josn")
                        .strictJsonSchema(true)
                        .build();
                Chef chef=AiServices.create(Chef.class,model);
                Recipe recipe = chef.createRecipeFrom("土豆", "牛肉", "胡萝卜", "洋葱", "青椒","酱油","盐","辣椒");
                System.out.println(recipe);

                CreateRecipePrompt prompt = new CreateRecipePrompt("土豆牛肉", Arrays.asList("土豆", "牛肉", "胡萝卜", "洋葱", "青椒","酱油","盐","辣椒"));
                Recipe recipe1 = chef.craeteRecipe(prompt);
                System.out.println(recipe1);
            }
        }

        ///////带记忆的ai服务
        //1.memory的类型:message,token
        static class ServiceWithMemory{
            interface Assistant{
                String chat(String message);
            }
            public static void main(String[] args) {
                //基于消息messagewindow的记忆
                ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(1000);
                Assistant assistant=AiServices.builder(Assistant.class)
                        .chatModel(model)
                        .chatMemory(chatMemory)
                        .build();

                String answer = assistant.chat("你好,我是张三,我是一名大三的学生,我的专业是信息与计算科学.我学过java,数据库,spring data jpa,AI,langchain4j");
                System.out.println(answer);
                String answer2 = assistant.chat("请给我一些就业提示");
                System.out.println(answer2);

            }
        }
        //区分用户id的带记忆ai服务
        static class ServiceWithMemoryAndUserId{
            interface Assistant{
                String chat(@MemoryId int memoryId,@UserMessage String message);
            }
            public static void main(String[] args) {
                ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(1000);
                Assistant assistant=AiServices.builder(Assistant.class)
                       .chatModel(model)
                       .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(1000))
                       .build();
                String a1=assistant.chat(1,"你好,我是张三,我是一名大三的学生,我的专业是信息与计算科学.我学过java,数据库,spring data jpa,AI,langchain4j");
                System.out.println(a1);
                String a2=assistant.chat(2,"我是李四,我是软件工程的大三学生");
                System.out.println(a2);
                String a3=assistant.chat(1,"请给我一些就业提示");
                System.out.println(a3);
                String a4=assistant.chat(2,"请给我一些就业提示");
                System.out.println(a4);
            }
        }
    }
}
